#region LGPL License
//
//Adriano Ribeiro <adribeiro@gmail.com>
//
//Copyright (c) 2007 Mono Overlay Routing Foundation Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// 
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


#endregion


using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;

using Monorf;
//using Monorf.Serialization;


namespace Monorf.Net
{
    /// <summary>
    /// Description of UdpListener.
    /// </summary>
    public class UdpListener : BaseListener<CommunicationState>
    {

        public UdpListener(Int32 messageSize, CommunicationLink<CommunicationState> 
                            communicationData, Handle handleListener):
            base(messageSize, communicationData, handleListener)
        {
        }

        #region properties

        #endregion


        /// <summary>
        /// start async listening
        /// </summary>
        /// <param name="listenSocket"></param>
        /// <returns></returns>
        public override void BeginAccept(Object state)
        {
            //receive remote endpoint
            EndPoint remoteEP = AddressEndPoint.CreateDummyEndPoint();

            TransmissionState transmissionState = new TransmissionState((Handle)state,
                                                                        m_messageBuffer.CreateBuffer());

            try
            {
                lock (transmissionState.Lock)
                {
                    IAsyncResult result =
                            transmissionState.Socket.BeginReceiveFrom(transmissionState.Buffer,
                                                                      0,
                                                                      transmissionState.Buffer.Length,
                                                                      SocketFlags.None,
                                                                      ref remoteEP,
                                                                      m_receiveCompletion,
                                                                      transmissionState);
                }
            }
            catch (SocketException ex)
            {
                if (ex.SocketErrorCode == SocketError.ConnectionReset)
                    return;
            }
        }

        /// <summary>
        /// completion estado for received data.
        /// </summary>
        /// <param name="result"></param>
        protected override void AcceptCompleteCallBack(IAsyncResult result)
        {

            //receive remote endpoint
            EndPoint remoteEP = AddressEndPoint.CreateDummyEndPoint();
            CommunicationState communicatioData = null;
            TransmissionState transmissionState = (TransmissionState)result.AsyncState;

            try
            {

                lock (transmissionState.Lock)
                {

                    Int32 bytes =
                            transmissionState.Socket.EndReceiveFrom(result, ref remoteEP);

                    communicatioData = new CommunicationState(transmissionState.Buffer, remoteEP);
                }

                EndAccept(communicatioData);

                //async listening loop
                if (!m_stop)
                    base.Listen();
            }
            catch (SocketException ex)
            {
                if (ex.SocketErrorCode == SocketError.ConnectionReset)
                    return;

                communicatioData = new CommunicationState(transmissionState.Buffer, remoteEP);
                communicatioData.CommunicationExcetion = ex;

                EndAccept(communicatioData);
            }
        }
    }
}
